GtkSnapshot: Reuse snapshot state objects
authorAlexander Larsson <alexl@redhat.com>
Wed, 11 Jan 2017 10:41:46 +0000 (11:41 +0100)
committerAlexander Larsson <alexl@redhat.com>
Wed, 11 Jan 2017 10:41:46 +0000 (11:41 +0100)
Rather than allocate new ones all the time we reuse the previous ones.
We just clear them and save them in the parent for later reuse.

gtk/gtksnapshot.c
gtk/gtksnapshotprivate.h

index e17005828a4c515ee7e2087e5c21d6e8880cf823..72f1b1586f832e8d175f7018996857706e9487ad 100644 (file)
@@ -84,11 +84,18 @@ gtk_snapshot_state_new (GtkSnapshotState       *parent,
 {
   GtkSnapshotState *state;
 
-  state = g_slice_new0 (GtkSnapshotState);
-
-  state->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify) gsk_render_node_unref);
+  if (parent != NULL && parent->cached_state != NULL)
+    {
+      state = parent->cached_state;
+      parent->cached_state = NULL;
+    }
+  else
+    {
+      state = g_slice_new0 (GtkSnapshotState);
+      state->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify) gsk_render_node_unref);
+      state->parent = parent;
+    }
 
-  state->parent = parent;
   state->name = name;
   if (clip)
     state->clip_region = cairo_region_reference (clip);
@@ -99,16 +106,21 @@ gtk_snapshot_state_new (GtkSnapshotState       *parent,
   return state;
 }
 
+static void
+gtk_snapshot_state_clear (GtkSnapshotState *state)
+{
+  g_ptr_array_set_size (state->nodes, 0);
+  g_clear_pointer (&state->clip_region, cairo_region_destroy);
+  g_clear_pointer (&state->name, g_free);
+}
+
 static void
 gtk_snapshot_state_free (GtkSnapshotState *state)
 {
+  if (state->cached_state)
+    gtk_snapshot_state_free (state->cached_state);
+  gtk_snapshot_state_clear (state);
   g_ptr_array_unref (state->nodes);
-
-  if (state->clip_region)
-    cairo_region_destroy (state->clip_region);
-
-  g_free (state->name);
-
   g_slice_free (GtkSnapshotState, state);
 }
 
@@ -697,7 +709,13 @@ gtk_snapshot_pop (GtkSnapshot *snapshot)
                               state->nodes->len,
                               state->name);
 
-  gtk_snapshot_state_free (state);
+  if (snapshot->state == NULL)
+    gtk_snapshot_state_free (state);
+  else
+    {
+      gtk_snapshot_state_clear (state);
+      snapshot->state->cached_state = state;
+    }
 
   return node;
 }
index 31415588baff21ddddd5af7d80811f0bc9c6fdc6..2384a8b55f7d0df8c27076556c006b72ce27e532 100644 (file)
@@ -31,6 +31,7 @@ typedef GskRenderNode * (* GtkSnapshotCollectFunc) (GtkSnapshotState *state,
 
 struct _GtkSnapshotState {
   GtkSnapshotState      *parent;
+  GtkSnapshotState      *cached_state; /* A cleared state object we can (re)use */
 
   char                  *name;
   GPtrArray             *nodes;